/*
 * Copyright (c) 2014 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

/*
 * This is nacl-clang's crtbegin file (crtbegin.o, crtbeginS.o, crtbeginT.o).
 * Currently we only support static linking and it only supports being used
 * as crtbeginT.o (see __dso_handle below).
 */

/*
 * HACK:
 * The real structure is defined in unwind-dw2-fde.h
 * this is something that is at least twice as big.
 */
struct object {
  void *p[16] __attribute__((aligned(8)));
};

extern void __register_frame_info(void *begin, struct object *ob);
extern void __deregister_frame_info(const void *begin);

typedef void (*initfini_func_ptr) (void);

/*
 * Exception handling frames are aggregated into a single section called
 * .eh_frame.  The runtime system needs to (1) have a symbol for the beginning
 * of this section, and needs to (2) mark the end of the section by a NULL.
 */

static char __EH_FRAME_BEGIN__[]
    __attribute__((section(".eh_frame"), aligned(4)))
    = { };

static void __do_eh_ctor(void) {
  static struct object object;
  __register_frame_info (__EH_FRAME_BEGIN__, &object);
}

static initfini_func_ptr __do_eh_ctor_init_array_entry[]
    __attribute__ ((__used__, section(".init_array")))
    = { __do_eh_ctor };

static void __do_eh_dtor(void) {
  __deregister_frame_info(__EH_FRAME_BEGIN__);
}

static initfini_func_ptr __do_eh_dtor_fini_array_entry[]
    __attribute__ ((__used__, section(".fini_array")))
    = { __do_eh_dtor };

/*
 * References to __dso_handle are generated by the compiler front end,
 * which uses it when registering destructors for C++ global
 * variables.  The compiler will generate a function call like the
 * following in an initializer:
 *
 *   __cxa_atexit(destructor_func, &global_obj, &__dso_handle);
 *
 * __cxa_atexit() arranges for destructor_func(&global_obj) to be
 * called on exit() or when the DSO uniquely identified by
 * &__dso_handle is dlclose()'d.  See:
 * http://gcc.gnu.org/ml/gcc-patches/1999-12n/msg00664.html
 *
 * (Note that __cxa_* functions are usually provided by libsupc++ or
 * its equivalent, but __cxa_atexit() happens to be provided by libc.)
 *
 * __dso_handle is zero for the main executable, which is the only
 * case currently supported by this crtbegin.
 */

void *__dso_handle = 0;
